/*
* Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
* 
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Eclipse Public License
* Version 1.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/EPL-1.0 and read it before using this file.
*/

#include "stdafx.h"
#include "CScriptableImageIndexer.h"
#include "CScriptableImage.h"
#include "strings.h"
#include "convert.h"


#define INDEXBASE 10000L


CScriptableImageIndexer::CScriptableImageIndexer()
    : m_model( NULL ),
    m_scriptableControl( NULL )
{
}

CScriptableImageIndexer::~CScriptableImageIndexer()
{
}

STDMETHODIMP CScriptableImageIndexer::get_length( VARIANT* pVal )
{
    if ( m_model )
    {
        pVal->vt = VT_INT;
        pVal->intVal = m_model->getImageCount();
    }
    return S_OK;
}

STDMETHODIMP CScriptableImageIndexer::get_count( VARIANT* pVal )
{
    if ( m_model )
    {
        pVal->vt = VT_INT;
        pVal->intVal = m_model->getImageCount();
    }
    return S_OK;
}

STDMETHODIMP CScriptableImageIndexer::GetIDsOfNames( _In_ REFIID riid, _In_count_(cNames) _Deref_pre_z_ LPOLESTR* rgszNames, _In_ UINT cNames, _In_ LCID lcid, _Out_ DISPID* rgdispid )
{
    if ( cNames == 1 )
    {
        bool isIndex = false;
        int index = 0;
        wchar_t* name = rgszNames[ 0 ];

        bool is0 = String::Equal( L"0", name ) == 0;

        if ( is0 ) isIndex = true;
        else
        {
            if ( ( index = Convert::ToInt( name ) ) != 0 )
            {
                isIndex = true;
            }
        }

        if ( isIndex )
        {
            *rgdispid = INDEXBASE + ( LONG ) index;
            return S_OK;
        }
    }

    return BaseDispatch::GetIDsOfNames( riid, rgszNames, cNames, lcid, rgdispid );
}

STDMETHODIMP CScriptableImageIndexer::Invoke( _In_ DISPID dispidMember, _In_ REFIID riid, _In_ LCID lcid, _In_ WORD wFlags, _In_ DISPPARAMS* pdispparams, _Out_opt_ VARIANT* pvarResult, _Out_opt_ EXCEPINFO* pexcepinfo, _Out_opt_ UINT* puArgErr )
{
    if ( dispidMember >= INDEXBASE )
    {
        int index = ( int ) ( dispidMember - INDEXBASE );

        return GetItemByIndex( index, pvarResult );
    }

    return BaseDispatch::Invoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr );
}

void CScriptableImageIndexer::setScriptableControl( CScriptableControl* value )
{
    m_scriptableControl = value;
    m_model = value->m_plugin->getModel(); 
}

HRESULT CScriptableImageIndexer::GetItemByIndex( int index, VARIANT* pvarResult )
{
    HRESULT result = S_OK;

    if ( index >= 0 && index < m_model->getImageCount() )
    {
        const PluginImage* image = m_model->getImage( index );
        void* tag = image->getTag();

        IDispatch* disp = NULL;
        if ( tag == NULL )
        {
            IUnknown* iu = NULL;
            if ( SUCCEEDED( ::CoCreateInstance( CLSID_ScriptableImage, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, ( void** ) &iu ) ) )
            {
                CScriptableImage* i = ( CScriptableImage* ) iu;
                i->setImage( image );
                i->setScriptableControl( m_scriptableControl );
                tag = iu;
                PluginImage* pluginImage = const_cast<PluginImage*>( image );
                pluginImage->setTag( ( void* ) tag );
                pluginImage->setEventHandler( i );
            }
        }

        if ( tag )
        {
            IUnknown* iu = ( IUnknown* ) tag;
            if ( iu->QueryInterface( IID_IDispatch, ( void** ) &disp ) != S_OK )
            {
                throw "cannot get image disp!";
            }

            pvarResult->vt = VT_DISPATCH;
            pvarResult->pdispVal = disp;

            //return S_OK;
        }
        else
        {
            result = DISP_E_EXCEPTION;
        }
    }
    else
    {
        result = DISP_E_MEMBERNOTFOUND;
    }

    return result;
}

STDMETHODIMP CScriptableImageIndexer::get_current( VARIANT* pResult )
{
    int selectedImageIndex = m_model->getSelectedImageIndex();
    return GetItemByIndex( selectedImageIndex, pResult );
}
